package security.SecurityUtil.login;


import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import finals.Constant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Service;
import security.entity.YxActor;
import security.entity.YxLogin;
import security.service.IYxActorService;
import security.service.IYxLoginService;
import security.util.RedisUtil;

import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.TimeUnit;


/**
 * <p>类名: CustomUserDetailService</p>
 * <p>描述:TODO</p>
 * <p>创建人: liyp</p>
 * <p>创建时间: 2020/1/9 14:16</p>
 * <p>@version 2.0  </p>
 * <p>修改内容: ......</p>
 * <p>修改说明: ......</p>
 * <p>修改时间: ......</p>
 * <p>修改人: ......</p>
 * <p>每次修改，请增加上述修改信息说明</>
 */
@Service
public class CustomUserDetailService implements UserDetailsService{

    @Autowired
    IYxLoginService iYxLoginService;

    @Autowired
    IYxActorService iYxActorService;

    @Autowired
    RedisTemplate redisTemplate;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        CustomerUserDetails customerUserDetails = null;
        YxLogin yxLogin = iYxLoginService.selectByCode(s);
        if(null == yxLogin){
            throw new BadCredentialsException("用户" + s + "不存在");
        }
        YxActor yxActor = iYxActorService.getById(yxLogin.getSaId());
        if(null == yxLogin){
            throw new BadCredentialsException("用户" + s + "不存在密码数据");
        }
        //这里要获取用户所有的权限，放在自定义的用户信息里面，待完善
        customerUserDetails = new CustomerUserDetails(yxActor.getId(),
                yxLogin.getName(),
                yxActor.getPassword(),
                "0",
        true,
        true,
        true,
        null);
        return customerUserDetails;
    }

    /**
     *
     * 功能描述：这里重新获取用户信息是为了获取用户权限
     * 作   者： liyp
     * 创建时间： 2020/1/16 16:30
     * 参数: [userName]
     *  返回值： org.springframework.security.core.userdetails.UserDetails
     */
    public UserDetails getUserLoginInfo(String userName){
        String salt = redisTemplate.opsForValue().get("token:"+userName).toString();
        UserDetails user = loadUserByUsername(userName);
        //将salt放到password字段返回,后续重写认证的provider，provider会从该方法中获取加密盐值
        return User.builder().username(user.getUsername()).password(salt).authorities(null == user.getAuthorities()? new ArrayList<>() : user.getAuthorities()).build();
    }

    /**
     *
     * 功能描述：登陆成功，记录用户加密盐值
     * 作   者： liyp
     * 创建时间： 2020/1/16 16:14
     * 参数: [userDetails]
     *  返回值： java.lang.String
     */
    public String createToken(UserDetails userDetails){
        String salt = BCrypt.gensalt();
        redisTemplate.opsForValue().set(Constant.TOKEN_PERFFEX+userDetails.getUsername(), salt, 3600, TimeUnit.SECONDS);
        Algorithm algorithm = Algorithm.HMAC256(salt);
        //设置1小时后过期
        Date date = new Date(System.currentTimeMillis()+3600*1000);
        return JWT.create()
                .withSubject(userDetails.getUsername())
                .withExpiresAt(date)
                .withIssuedAt(new Date())
                .sign(algorithm);
    }
}
